<template>
    <div>
        <template v-for="(cur, index) in valueIdList">
            <display-condition-item
                :key="index"
                :value="cur.id || cur.itemIds"
                :hasOptions="checkOptions(valueIdList, cur.id)"
                :controlId="(cur.id || cur.itemIds) ? cur.itemIds : []"
                :itemControl="item"
                :list.sync="currentList"
                :itemList="itemList"
                @changeItemCascader="changeItemCascader($event, index)"
                @addOptionId="addOptionId($event, index)">
                <el-button type="text" @click="add(index)">添加</el-button>
                <el-button type="text" @click="delNow(cur.id, index)">删除</el-button>
            </display-condition-item>
        </template>
        <template v-if="!valueIdList.length">
            <el-button @click="add(-1)">添加显示条件</el-button>
        </template>
    </div>
</template>

<script lang="ts">
import { Component, PropSync, Vue, Watch } from "vue-property-decorator";
import DisplayConditionItem from "../display-condition-item/index.vue";

@Component({
    name: "DisplayCondition",
    components: {
        DisplayConditionItem
    }
})
export default class DisplayCondition extends Vue {
    @PropSync("itemControl", { type: Object, default: {} }) readonly item: any;
    @PropSync(
        'list',
        {
            type: Array,
            default: () => {
                return [];
            }
        })
    readonly currentList!: any[];

    @Watch("currentList", { immediate: true, deep: true })
    changeItemList() {
        const getItem = (arr: any) => {
            let list: any[] = [];
            arr.forEach((item: any) => {
                if (item.itemType === 2) {
                    if (item.tempId !== this.item.tempId) {
                        /**
                         * 没有被绑定的，但是绑定了其他，不行
                         * 已经绑定的，不行
                         * 没有绑定的，也没有绑定别人，可以
                         */
                        const nodeIndex = this.allOnlyItem.findIndex((cur: any) => cur.cascadeId === item.tempId);
                        if (!item.cascadeId && nodeIndex === -1) {
                            list.push(item);
                        }
                        if (item.cascadeId && item.cascadeId === this.item.tempId) {
                            list.push(item);
                            const optionsIdList = item.cascadeOptionIds;
                            optionsIdList.forEach((it: any) => {
                                const idIndex = this.valueIdList.findIndex((i: any) => i.id === it);
                                if (idIndex !== -1) {
                                    if (this.valueIdList[idIndex].itemIds && !this.valueIdList[idIndex].itemIds.includes(item.tempId)) {
                                        this.valueIdList[idIndex].itemIds.push(item.tempId);
                                    }
                                } else {
                                    this.valueIdList.push({
                                        id: it,
                                        optionId: it,
                                        itemIds: [item.tempId]
                                    });
                                }
                            });
                        }
                    }
                } else if (item.itemType === 0) {
                    list = list.concat([], getItem(item.items));
                }
            });
            return list;
        };

        this.itemList = getItem(this.currentList);
        if (!this.valueIdList.length) {
            this.valueIdList = [{ id: "" }];
        }
    }

    get _item() {
        return JSON.parse(JSON.stringify(this.item));
    }

    @Watch("_item", { deep: true })
    changItem(newValue: any, oldValue: any) {
        if (newValue.tempId === oldValue.tempId) {
            if (newValue.options.length === oldValue.options.length) {
                const newOptions = newValue.options.map((item: any) => item.tempId || item.id);
                const oldOptions = oldValue.options.map((item: any) => item.tempId || item.id);
                if (newOptions.join() === oldOptions.join()) {
                    return;
                }
            }
            this.valueIdList = [{ id: "" }];

            const delItem = (arr: any) => {
                arr.forEach((item: any) => {
                    if (item.itemType === 2) {
                        if (item.cascadeId === this.item.tempId) {
                            item.cascadeId = null;
                            item.cascadeOptionIds = null;
                        }
                    } else {
                        delItem(item.items);
                    }
                });
            };

            delItem(this.currentList);
        } else {
            this.valueIdList = [];
            this.changeItemList();
        }
    }

    get allOnlyItem() {
        const getItem = (arr: any) => {
            let list: any[] = [];
            arr.forEach((item: any) => {
                if (item.itemType === 2) {
                    list.push(item);
                } else {
                    list = list.concat([], getItem(item.items));
                }
            });
            return list;
        };

        return getItem(this.currentList);
    }

    /**
     * 绑定关系
     * [{
     *     id: 表单选项id,
     *     optionId: 表单选项id,
     *     itemIds: [被绑定的表单项id]
     * }]
     */
    valueIdList: any[] = []
    // 铺平表单项列表
    itemList: any[] = []

    add(index: any) {
        this.valueIdList.splice(index + 1, 0, { id: "" });
    }

    delNow(cur: any, index: any) {
        this.valueIdList.splice(index, 1);

        const delItem = (arr: any) => {
            arr.forEach((item: any) => {
                if (item.itemType === 2) {
                    if (item.cascadeId === this.item.tempId && item.cascadeOptionIds.includes(cur)) {
                        item.cascadeId = null;
                        if (item.cascadeOptionIds.length === 1) {
                            item.cascadeOptionIds = null;
                        } else {
                            item.cascadeOptionIds.splice(cur.indexOf(item.cascadeOptionIds), 1);
                        }
                    }
                } else {
                    delItem(item.items);
                }
            });
        };

        delItem(this.currentList);
    }

    // 确认可选选项
    checkOptions(list: any, cur: any) {
        return list.filter((item: any) => item !== cur);
    }

    // 添加当前选中项id
    addOptionId(value: any, index: any) {
        this.valueIdList[index].id = value;
    }

    // 修改选项后，在这里统一处理值，为了后面多对一，一对多，多对多
    changeItemCascader(data: any, index: any) {
        const { itemValueId: optionId, chooseIdList: itemIds } = data;
        this.valueIdList[index].optionId = optionId;
        this.valueIdList[index].itemIds = itemIds;

        this.addAttrToItem();
    }

    addAttrToItem() {
        // 所有需要绑定的表单项id
        let allControlId = this.valueIdList.map((item: any) => item.itemIds);
        const flatten = (arr: any) => {
            return [].concat(...arr.map((i: any) => Array.isArray(i) ? flatten(i) : i));
        };
        // 铺平
        allControlId = flatten(allControlId).filter((item: any) => !!item);
        // 去重
        allControlId = Array.from(new Set(allControlId));
        const getItem = (arr: any) => {
            arr.forEach((item: any) => {
                if (item.itemType === 2) {
                    // 是要设置的表单项
                    if (allControlId.includes(item.tempId)) {
                        const optionIdList = this.valueIdList.filter((cur: any) => cur.itemIds && cur.itemIds.includes(item.tempId));
                        item.cascadeId = this.item.tempId;
                        item.cascadeOptionIds = optionIdList.map((it: any) => it.id);
                    } else {
                        // 如果不在要设置的里面，但是表单项id相同，就是需要删除的
                        item.cascadeId = this.item.tempId === item.cascadeId ? null : item.cascadeId || null;
                        item.cascadeOptionIds = this.item.tempId === item.cascadeOptionIds ? null : item.cascadeOptionIds || null;
                    }
                } else {
                    getItem(item.items);
                }
            });
        };

        getItem(this.currentList);
    }
}
</script>
